﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using GameBase;

namespace GalaxyPresident
{
    public abstract class Unit : PlanetObjectOwner,AutoAttack
    {
        private static Texture2D explosionTexture = Constant.content.Load<Texture2D>(@"Resources/Ammo/airExplosion");
        public enum UNIT_STATE { idle, move, attack, die };
        protected float _energyPoint;
        protected float _speed = 5;
        protected float _rangeAttack = 500;
        private UNIT_STATE _state = UNIT_STATE.idle;
        protected Vector2 _targetMove;
        //private float _heightForGravity = 200;
        private bool isMovingForAttack = false;
        private bool isOn = false;

        public bool IsOn
        {
            get { return isOn; }
            set { isOn = value; }
        }
        Team teamOwner;

        public Team TeamOwner
        {
            get { return teamOwner; }
            set { teamOwner = value; }
        }
        public Team GetTeamOwner()
        {
            return teamOwner;
        }
        public float GetRange()
        {
            return _rangeAttack;
        }
        CraftStation station;

        internal CraftStation Station
        {
            get { return station; }
            set { station = value; }
        }
        protected AttackingHelper _attackhelper;

        protected UNIT_STATE State
        {
            get { return _state; }
            set
            {
                _state = value;
                switch (value)
                {
                    case UNIT_STATE.idle:
                        sprite.FrameSequence = idleSequence;
                        sprite_s.FrameSequence = idleSequence_s;
                        break;
                    case UNIT_STATE.attack:
                        sprite.FrameSequence = workSequence;
                        sprite_s.FrameSequence = workSequence_s;
                        break;
                    case UNIT_STATE.die:
                        sprite.FrameSequence = collapseSequence;
                        sprite_s.FrameSequence = collapseSequence_s;
                        break;
                }
            }
        }

        public Unit(Planet planet)
            : base(planet)
        {
            if(planet != null)
                teamOwner = planet.TeamOwner;
            Scale = Constant.scalePlanetEntity;

            _explosion = new VisibleObject(explosionTexture, 2, 4);
            _explosion.Sprite.SetOriginPosition(ORIGIN_POSITION.Center);
            _explosion.Depth = 0.08f;
            _explosion.Sprite.IsPlayOneTime = true;
            _explosion.Sprite.Delay = 50;
            _explosion.Scale = Constant.scalePlanetEntity;

            //updatePlanetOwnerResources();
        }

        protected override void initInfo()
        {
            base.initInfo();
        }

        protected void initSprites(Planet planet)
        {
            sprite_s.SetOriginPosition(ORIGIN_POSITION.Center);
            if (planet != null)
                if (planet.TeamOwner == null)
                    sprite_s.Color = Color.Black;
                else
                    sprite_s.Color = planet.TeamOwner.TeamColor;
            AddSprite(sprite_s);

            sprite.SetOriginPosition(ORIGIN_POSITION.Center);
            sprite.Color = Color.White;
            AddSprite(sprite);
            depth = 0.1f + (float)Constant.random.NextDouble() * 0.7f;
        }

        public Unit clone()
        {
            if (this.isMyPlanetEnoughResourcesForProduce())
            {
                updatePlanetOwnerResources();
                return createInstance();
            }
            return null;
        }

        protected virtual Unit createInstance()
        {
            return null;
        }

        public void moveTo(Vector2 targetPos)
        {
            State = UNIT_STATE.move;
            _targetMove = targetPos;
        }

        private bool isAutoRemoveFromBaseView = false;
        public void autoRemoveFromBaseViewWhenMoveToComplete(Vector2 targetPos)
        {
            State = UNIT_STATE.move;
            _targetMove = targetPos;
            isAutoRemoveFromBaseView = true;
        }

        private void updateUnitRotation(Vector2 targetPos)
        {
            //Math.Atan2(b.Y - a.Y,b.X - a.X);
            float anglez = Helper.getAngleBetween(targetPos, Position);
            if (anglez == 0)
                return;
            sprite.Rotate = anglez;
            if (targetPos.X < position.X)
                sprite.Rotate += (float)Math.PI;
            sprite_s.Rotate = sprite.Rotate;
        }

        public void attackTo(PlanetObjectOwner obj)
        {
            if (this == obj || obj == null)
                return;

            _attackhelper.attackTo(obj);
            State = UNIT_STATE.attack;
        }

        float currentTimeForAttack = 0;
        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            //switch (State)
            //{
            //    case UNIT_STATE.idle:
            //        break;
            //    case UNIT_STATE.move:
            //        moveProcessing();
            //        break;
            //    case UNIT_STATE.attack:
            //        //moveProcessing();
            //        currentTimeForAttack += gameTime.ElapsedGameTime.Milliseconds;
            //        if (currentTimeForAttack > 300)
            //        {
            //            currentTimeForAttack = 0;
            //            attackProcessing();
            //        }
            //        break;
            //    case UNIT_STATE.die:
            //        break;
            //}
        }
        public override void UpdateInfo(GameTime gameTime)
        {
            base.UpdateInfo(gameTime);
            switch (State)
            {
                case UNIT_STATE.idle:
                    break;
                case UNIT_STATE.move:
                    moveProcessing();
                    break;
                case UNIT_STATE.attack:
                    //moveProcessing();
                    currentTimeForAttack += gameTime.ElapsedGameTime.Milliseconds;
                    if (currentTimeForAttack > 300)
                    {
                        currentTimeForAttack = 0;
                        attackProcessing();
                    }
                    break;
                case UNIT_STATE.die:
                    break;
            }
        }

        protected override void destroyProcessing()
        {
            base.destroyProcessing();
            State = UNIT_STATE.die;
        }

        protected override void removeObjectWhenDestroy()
        {
            if (parent != null)
            {
                parent.RemoveChild(this);
            }
            PlanetOwner.Units.Remove(this);
            //PlanetOwner.TeamOwner.Units.Remove(this);
        }

        public string getUnitInfoString()
        {
            return  "Material: " + ((int)meterialCost).ToString()
                + "\nMoney   : " + ((int)moneyCost).ToString()
                + "\nEnergy  : " + ((int)energyCost).ToString()
                + "\n"
                + "\nRange   : " + ((int)_rangeAttack).ToString()
                + "\nHealth  : " + ((int)_healthPoint).ToString()
                + "\nEnergy  : " + ((int)_energyPoint).ToString()
                + "\nSpeed   : " + ((int)_speed).ToString()
                + "\nDefense : " + (_defense * 100).ToString() + "%";
        }

        #region private methods processing.
        private void attackProcessing()
        {

            Vector2 distance = _attackhelper.TargetAttack.Position - Position;
            if (distance.Length() > _rangeAttack)
            {
                moveTo(findPostionForMove(Position, _attackhelper.TargetAttack.Position, distance.Length() - _rangeAttack));
                isMovingForAttack = true;
            }
            else
            {
                this.updateUnitRotation(_attackhelper.TargetAttack.Position);
                this.updateUnitDirection(_attackhelper.TargetAttack.Position);

                _attackhelper.attackProcessing(Position);

                State = UNIT_STATE.idle;
            }
        }

        private Vector2 findPostionForMove(Vector2 Pos, Vector2 targetPos, float distance)
        {
            // A(Position)-------C--------------B(TargetPosition)
            // AC = distance
            // C = result

            Vector2 result = Vector2.Zero;

            Vector2 AB = targetPos - Pos;
            float k = distance / AB.Length();
            Vector2 AC = AB * k;
            result = Pos + AC;

            return result;
        }

        private void moveProcessing()
        {
            //float heightz = _planetOwner.Diameter / 2 * Constant.scaleDetailPlanet + _heightForGravity;
            //if (Position.Length() > heightz + _speed || Position.Length() < heightz - _speed)
            //{
                Position = MotionEffects.Move(Position, _targetMove, _speed * scale);

                this.updateUnitRotation(_targetMove);
                this.updateUnitDirection(_targetMove);

                if (Position == _targetMove)
                {
                    State = UNIT_STATE.idle;
                    if (isMovingForAttack)
                    {
                        isMovingForAttack = false;
                        State = UNIT_STATE.attack;
                    }

                    if (isAutoRemoveFromBaseView)
                    {
                        isAutoRemoveFromBaseView = false;
                        parent.RemoveChild(this);
                        _planetOwner = null;
                    }
                }
            //}
            //else
            //{
            //    Position = findPostionForMove(position, _targetPosition, -_speed);
            //    State = UNIT_STATE.idle;
            //}

            //if (Position.Y > targetPos.Y && sprite.Effect != SpriteEffects.None)
            //{
            //    sprite.Effect = SpriteEffects.None;
            //    sprite_s.Effect = SpriteEffects.None;
            //}
            //else if (Position.Y < targetPos.Y && sprite.Effect != SpriteEffects.FlipVertically)
            //{
            //    sprite.Effect = SpriteEffects.FlipVertically;
            //    sprite_s.Effect = SpriteEffects.FlipVertically;
            //}
        }

        private void updateUnitDirection(Vector2 targetPos)
        {
            if (Position.X > targetPos.X && sprite.Effect != SpriteEffects.None)
            {
                sprite.Effect = SpriteEffects.None;
                sprite_s.Effect = SpriteEffects.None;
            }
            else if (Position.X < targetPos.X && sprite.Effect != SpriteEffects.FlipHorizontally)
            {
                sprite.Effect = SpriteEffects.FlipHorizontally;
                sprite_s.Effect = SpriteEffects.FlipHorizontally;
            }
        }
        #endregion
    }
}
